home *** CD-ROM | disk | FTP | other *** search
- TITLE Add Entry to an Ordered List (EX57.ASM)
- PAGE ,132
- DATA SEGMENT PARA 'DATA'
- START_ADDR DW ?
- DATA ENDS
- OUR_CODE SEGMENT PARA 'CODE'
- PUBLIC ADD_TO_OL
- ADD_TO_OL PROC FAR
- ASSUME CS:OUR_CODE,DS:DATA
- PUSH DS ;Save caller's registers
- PUSH CX
- PUSH SI
- PUSH BX
- MOV BX,SEG DATA ;Initialize DS
- MOV DS,BX
- CALL B_SEARCH ;Is the value in the list?
- JNC GOODBYE ; If so, exit
- MOV BX,SI ; If not, copy compare addr. to Bx
- MOV CX,ES:[DI] ;Find address of last element
- SHL CX,1
- ADD CX,DI ; and put it in CX
- PUSH CX ;Save this address on the stack
- SUB CX,SI ;Calculate no. of words to be moved
- SHR CX,1
- CMP AX,ES:[SI] ;Should compare el. be moved,too?
- JA EXCLUDE
- INC CX ; Yes. Increase move count by 1
- JNZ CHECK_CNT
- EXCLUDE: ADD BX,2 ; No. Adjust insert pointer
- CHECK_CNT: CMP CX,0 ;Move count = 0?
- JNE MOVE_ELS
- POP SI ; If so, store value at end of list
- MOV ES:[SI+2],AX
- JMP SHORT INC_CNT ; then go increase element count
- MOVE_ELS: POP SI ;Load start address for move
- PUSH BX ;Save insert address on stack
- MOVE_ONE: MOV BX,ES:[SI] ;Move one element down in list
- MOV ES:[SI+2],BX
- SUB SI,2 ;Point to next element
- LOOP MOVE_ONE ;Repeat until all are moved
- POP BX ;Retrieve insert address
- MOV ES:[BX],AX ;Insert AX in the list
- INC_CNT: INC WORD PTR ES:[DI] ;Add 1 to element count
- GOODBYE: POP BX ;Restore registers
- POP SI
- POP CX
- POP DS
- RET ; and exit
- ADD_TO_OL ENDP
- ;
- ; This is the B_SEARCH procedure from Example 5-6.
- ;
- B_SEARCH PROC
- CMP AX,ES:[DI+2] ;Search value < or = first el.?
- JA CHK_LAST ; No. Go check last element
- LEA SI,ES:[DI+2] ; Yes. Fetch addr. of first el.
- JE EXIT_1ST ;If value = 1st element, exit
- STC ;If value < 1st element, set CF
- EXIT_1ST: RET
- CHK_LAST: MOV SI,ES:[DI] ;Point to last element
- SHL SI,1
- ADD SI,DI
- CMP AX,ES:[SI] ;Search value > or = last el.?
- JB SEARCH ; No. Go search list
- JE EXIT_LAST ; Yes. Exit if value = last el.
- STC ;If value > last element, set CF
- EXIT_LAST: RET ; and then exit
- ;
- ; Search for value within the list.
- ;
- SEARCH: MOV START_ADDR,DI ;Save starting address in memory
- MOV SI,ES:[DI] ;Fetch index
- EVEN_IDX: TEST SI,1 ;Force index to an even value
- JZ ADD_IDX
- INC SI
- ADD_IDX: ADD DI,SI ;Calculate next search address
- COMPARE: CMP AX,ES:[DI] ;Search value found?
- JE ALL_DONE ; If so, exit
- JA HIGHER ; Otherwise, find correct half
- ;
- ; These instructions are executed if the search value is lower
- ; in the list.
- ;
- CMP SI,2 ;Index = 2?
- JNE IDX_OK
- NO_MATCH: STC ; If so, set CF
- JE ALL_DONE ; and exit
- IDX_OK: SHR SI,1 ; If not, divide index by 2
- TEST SI,1 ;Force index to an even value
- JZ SUB_IDX
- INC SI
- SUB_IDX: SUB DI,SI ;Calculate next address
- JMP SHORT COMPARE ;Go check this element
- ;
- ; These instructions are executed if the search value is higher
- ; in the list.
- ;
- HIGHER: CMP SI,2 ;Index = 2?
- JE NO_MATCH ; If so, go set CF and exit
- SHR SI,1 ; If not, divide index by 2
- JMP SHORT EVEN_IDX ;Go check next element
- ;
- ; Following are exit instructions.
- ;
- ALL_DONE: MOV SI,DI ;Move compare address into SI
- MOV DI,START_ADDR ;Restore starting address
- RET ; and exit
- B_SEARCH ENDP
- OUR_CODE ENDS
- END ADD_TO_OL
-